終於~終於~
我們來到最後一天啦!
在最後一天的內容,我們要來談在開發過程中
可能會遇到的問題與解決方式
| 類型 | 設定名稱 | 說明 | 
|---|---|---|
| Parent circuit breaker | indices.breaker.total.use_real_memory | 確定parent breaker是否應考慮實際記憶體使用情況 (true),還是僅考慮child circuit breakers保留的記憶體量 (false)。 預設為 true。 | 
| Parent circuit breaker | indices.breaker.total.limit | parent breaker的整體記憶體限制。如果indices.breaker.total.use_real_memory設為true,為JVM heap的95%,反之則為70% | 
| Field data circuit breaker | indices.breaker.fielddata.limit | 將field載入field data cache所需要的記憶體量,設為JVM heap的40%,如果是邏輯複雜的aggregation跟一些expensive query會觸發 | 
{
  'error': {
    'type': 'circuit_breaking_exception',
    'reason': '[parent] Data too large, data for [<http_request>] would be [123848638/118.1mb], which is larger than the limit of [123273216/117.5mb], real usage: [120182112/114.6mb], new bytes reserved: [3666526/3.4mb]',
    'bytes_wanted': 123848638,
    'bytes_limit': 123273216,
    'durability': 'TRANSIENT'
  },
  'status': 429
}
Caused by: org.elasticsearch.common.breaker.CircuitBreakingException: [parent] Data too large, data for [<transport_request>] would be [num/numGB], which is larger than the limit of [num/numGB], usages [request=0/0b, fielddata=num/numKB, in_flight_requests=num/numGB, accounting=num/numGB]
處理方法
GET _cat/nodes?v=true&h=name,node*,heap*

GET _nodes/stats/breaker
"breakers": {
        "model_inference": {
          "limit_size_in_bytes": 268435456,
          "limit_size": "256mb",
          "estimated_size_in_bytes": 0,
          "estimated_size": "0b",
          "overhead": 1,
          "tripped": 0 // 不是0的話代表超標
        },
        "inflight_requests": {
          "limit_size_in_bytes": 536870912,
          "limit_size": "512mb",
          "estimated_size_in_bytes": 0,
          "estimated_size": "0b",
          "overhead": 2,
          "tripped": 0
        },
"search.allow_expensive_queries": false來避免expensive searchesPOST _cache/clear?fielddata=true
"thread_pool": {
        "force_merge": {
          "type": "fixed",
          "size": 1,
          "queue_size": -1
        },
        "search_coordination": {
          "type": "fixed",
          "size": 2,
          "queue_size": 1000
        },
        "ml_datafeed": {
          "type": "scaling",
          "core": 1,
          "max": 512,
          "keep_alive": "1m",
          "queue_size": -1
        },
......
GET _cat/nodes?v=true&s=cpu:desc
紅箭頭為cpu使用率
GET _nodes/my-node,my-other-node/hot_threads
處理方法
// 獲取task_id
GET _tasks?actions=*search&detailed
{
  "nodes" : {
    "oTUltX4IQMOUUVeiohTt8A" : {
      "name" : "my-node",
      "transport_address" : "127.0.0.1:9300",
      "host" : "127.0.0.1",
      "ip" : "127.0.0.1:9300",
      "tasks" : {
        "oTUltX4IQMOUUVeiohTt8A:464" : { // 完整task_id
          "node" : "oTUltX4IQMOUUVeiohTt8A",
          "id" : 464,
          "type" : "transport",
          "action" : "indices:data/read/search",
          "description" : "indices[my-index], search_type[QUERY_THEN_FETCH], source[{\"query\":...}]",
          "start_time_in_millis" : 4081771730000,
          "running_time_in_nanos" : 13991383,
          "cancellable" : true
        }
      }
    }
  }
}
// 手動取消任務
POST _tasks/oTUltX4IQMOUUVeiohTt8A:464/_cancel
GET _cluster/health?filter_path=status,*_shards
{
  "status": "green",
  "active_primary_shards": 29,
  "active_shards": 59,
  "relocating_shards": 0,
  "initializing_shards": 0,
  "unassigned_shards": 0, //健康的cluster沒有未分配的shard
  "delayed_unassigned_shards": 0
}
GET _cat/shards?v=true&h=index,shard,prirep,state,node,unassigned.reason&s=state

p 代表是primary shard,r是代表replica shard
處理方法
GET my-index/_settings?flat_settings=true&include_defaults=true
GET _cluster/settings?flat_settings=true&include_defaults=true
POST /_cluster/reroute?metric=none
{
  "commands": [
    {
      "move": {
        "index": "test", "shard": 0,
        "from_node": "node1", "to_node": "node2"
      }
    },
    {
      "allocate_replica": {
        "index": "test", "shard": 1,
        "node": "node3"
      }
    },
		{
      "allocate_empty_primary": {
        "index": "my-index",
        "shard": 0,
        "node": "my-node",
        "accept_data_loss": "true"
      }
    }
  ]
}
在commands中有以下幾種操作
| 參數名稱 | 描述 | 
|---|---|
| move | 將shard從一個node移到另一個node | 
| cancel | 可以透過取消現有shard分配,然後重新初始化後讓primary shard同步現有的replica shard | 
| allocate_replica | 可以將unassigned的replica shard分配到node上 | 
| allocate_stale_primary | 會把primary shard分配到replica資料過時的node上,因為資料會進行覆蓋所以使用時需更加注意 | 
| allocate_empty_primary | 當node上的資料完全無法恢復的話,可以用這個方法,該方法就是把一個空的primary shard移到node上,如果使用該方法的話,即使後面node資料恢復也會被這個空的shard所覆蓋 | 
以上就是最後一天的內容啦
我們探討了不同面向的開發問題與處理方式
希望在開發時遇到類似的問題時,能夠提供解決問題的方向~
以上就是這30天的內容啦!
感謝任何有看到這裡的人
雖然很膚淺,但是看到有人訂閱或是對文章按like真的對我來說是很大的動力
讓我覺得我有幫助到任何在開發上遇到困難的人
我接觸ES的時間沒有很長,公司會需要用到的業務也不深
加上在開賽前其實大概只寫了3天份就直接開始了
每天這樣閱讀官方文檔,先吸收我能理解的部分,構思成我自己的東西
最後再重新編排文章,有時候可能一天就要花3-4小時才能寫出一篇XD
所以甚至有幾篇是在11:50幾分才能發出XD
原本幾篇文章介紹也會想要用更有趣的方式介紹
然後多做一些流程圖來讓內容更好理解
甚至多放一些我自己操作的內容與response來讓沒接觸過的人更能吸收
但是真的後來連我自己要理解官方文檔在說什麼就耗費我大量的時間跟精力XD
沒有辦法真的完成心中的目標應該是唯一的遺憾吧~
但是另一方面也很為自己感到驕傲
以前這些東西很多時候就是能debug或是處理掉問題就好
背後的原理或是要如何優化整個index或是cluster等等
我先前是沒有這麼多的認知以及理解
這次寫文章時,為了不要誤人子弟,所以在寫的時候我自己也會不斷的去檢查我自己寫的內容有沒有錯誤
遇到自己觀念也不清楚的地方,也會讓自己多去看其他文檔來補齊自己的觀念
在這30天中,我不只是把我會的東西整理出來變成文章
而是也隨著比賽過程讓我學習到更多ES的知識
但是同時也讓我認識到真的還有很多很多ES的相關內容是可以學習的
更別說有關kibana的observability了
這邊也說明一下我整個文章系列的參考對象
在初階的部分是參考udmey上面ES的相關課程
而深入探討的部分則是上完喬叔的進階課程才有更多想法
最後在寫的時候就看官方文檔來完整整個主題的內容
希望這系列的文章有幫助到螢幕前的你或妳~
對於一個去年10月轉職成軟體工程師的我來說
算是轉換跑道後除了自己的side project之外最令我自己滿意的成績單了~
如果後續有關於kibana的內容也會更新上來啦~希望不要挖坑然後不填坑XD
參考資料
circuit breaker errors:
https://www.elastic.co/guide/en/elasticsearch/reference/current/circuit-breaker-errors.html
cluster state error:
https://www.elastic.co/guide/en/elasticsearch/reference/current/red-yellow-cluster-status.html
cpu error:
https://www.elastic.co/guide/en/elasticsearch/reference/current/high-cpu-usage.html